﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Windows.Input;
using System.Windows.Threading;
using FM.Services;
using FM.矩阵.扩展;
using FM.矩阵.接口;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Logging;
using Microsoft.Practices.Prism.PubSubEvents;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;

namespace FM.矩阵.控制.Services
{


    public class 串口控制2008 : 启动基类, I串口控制
    {

        
        private readonly StringBuilder 返回数据 = new StringBuilder();

        private SerialPort _串口;

        private DispatcherTimer timer接收器;

        private DispatcherTimer timer批量发送;

        private bool 串口独占 = true;

        private int 定时次数 = 3;

        private bool _十六进制;

        private int _指令长度 = 8;

        private int _指令间隔毫秒 = 100;

        private Queue<I串口指令> 指令堆 = new Queue<I串口指令>();
        public ICommand 数据分析Command { get; set; }
        public void 发送指令(I串口指令 指令)
        {
            指令堆.Enqueue(指令);
            timer批量发送.Start();
        }

        public void 发送指令(IList<I串口指令> 指令)
        {
            指令.ForEach(x => 指令堆.Enqueue(x));
            timer批量发送.Start();
        }


        private I状态分析 矩阵状态分析1;

        public override void 启动()
        {

            定时器初始化();
            数据分析Command = new DelegateCommand<StringBuilder>(数据分析方法);
            串口测试();

            分析器自检测试();
        }

        private void 数据分析方法(StringBuilder r)
        {

        }


        private void 分析器自检测试()
        {

        }

        private void 串口初始化(串口配置 串口)
        {
            _串口 = new SerialPort(串口.串口名)
            {
                BaudRate = 串口.波特率,
                DtrEnable = true,
                ReadTimeout = 串口.读取超时毫秒,
                RtsEnable = true,
                WriteTimeout = 串口.写入超时毫秒,
                Parity = Parity.None, //无奇偶校验位
                StopBits = StopBits.One, //1个停止位
                ReceivedBytesThreshold = 2 //设置 DataReceived 事件发生前内部输入缓冲区中的字节数
            };
            _串口.DataReceived += 接收数据处理; //DataReceived事件委托 
        }

        private void 串口测试()
        {

            if (_串口.访问测试())
            {
                log.Log(("串口测试成功"), Category.Info, Priority.Medium);
            }
            else
            {
                log.Log(("串口测试失败:"), Category.Warn, Priority.Medium);
            }
        }

        private void 定时器初始化()
        {
            timer接收器 = new DispatcherTimer();
            timer接收器.Interval = new TimeSpan(0, 0, 0, 1); //1秒
            timer接收器.Tick += Timer接收器Tick;

            timer批量发送 = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, _指令间隔毫秒) };
            timer批量发送.Tick += timer批量发送_Tick;
        }

        private void timer批量发送_Tick(object sender, EventArgs e)
        {
            if (指令堆.Count == 0)
            {
                timer批量发送.Stop();
                return;
            }
            var 当前指令 = 指令堆.Dequeue();
            发送指令try(_串口, 当前指令.IsHex, 当前指令.信息);
        }

        private void Timer接收器Tick(object sender, EventArgs e)
        {
            定时次数--;
            if (定时次数 < 0)
            {
                timer接收器.Stop();
                读取串口返回数据();
                结果分析(返回数据);
                if (返回数据.Length > 0)
                {
                    log.Log(string.Format("{1}:{0}", 返回数据, ("串口数据清空")), Category.Info, Priority.Medium);
                    返回数据.Clear();
                }
                
            }
            else
            {
                结果分析(返回数据);
            }
        }

       

        private void 接收数据处理(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                读取串口返回数据();
                timer接收器.IsEnabled = true;
                定时次数 = 3;
            }
            catch (Exception ex)
            {
                log.Log(ex.Message, Category.Warn, Priority.Medium);
            }
        }

        private void 读取串口返回数据()
        {
            var r = new List<char>();
            while (_串口.IsOpen && _串口.BytesToRead > 0)
            {
                var ch = (char)_串口.ReadByte();
                r.Add(ch);
            }
            r.ForEach(cs => 返回数据.Append(cs));
        }

        private void 结果分析(StringBuilder 字符流)
        {
            try
            {
                if (数据分析Command != null) 
                    数据分析Command.Execute(字符流);
            }
            catch (Exception ee)
            {
                log.Log(("分析串口返回数据时出错:" + ee.Message), Category.Warn, Priority.Medium);
            }
        }

        //private void 发布执行分析结果(I任务结果分析 分析器)
        //{
        //    if (分析器.Is执行成功)
        //    {
        //        消息.发布状态栏("返回:", "执行成功");
        //    }
        //    if (分析器.分析结果.Count > 0)
        //    {
        //        运行时.单例.宣传部.GetEvent<矩阵状态发布事件>().Publish(分析器.分析结果.ToList());
        //    }
        //}

        private void 发布状态分析结果(IList<矩阵点> 分析结果)
        {
            //if (分析结果.Count > 0)
            //{
            //    消息.发布状态栏("返回:", "查询成功");
            //    运行时.单例.宣传部.GetEvent<矩阵状态发布事件>().Publish(分析结果.ToList());
            //}
        }

        #region 发送指令

        //public void 发送协议指令(端口协议 协议cs)
        //{
        //    var 指令 = 协议cs.控制指令;
        //    if (string.IsNullOrEmpty(指令))
        //    {
        //        log.Log(string.Format("协议<{0}>指令为空.", 协议cs.ID), Category.Info, Priority.Medium);
        //        return;
        //    }
        //    //返回模式 = 指令模式.任务执行;
        //    //指令堆.Enqueue(协议cs);
        //    //if (!timer批量发送.IsEnabled)
        //    //{
        //    //    timer批量发送.IsEnabled = true;
        //    //}

        //    //消息.发布状态栏("返回:", "等待...");
        //}

        internal void 发送指令try(SerialPort 串口cs, bool 十六进制, string 控制指令)
        {
            try
            {
                发送指令_立即(串口cs, 十六进制, 控制指令);
                var 完整提示1 = string.Format("成功:<{0}>", 控制指令);
                log.Log(完整提示1, Category.Info, Priority.Medium);
                var 简要提示1 = string.Format("成功:<{0}>", 控制指令.Length > 8 ? 控制指令.Substring(0, 8) + "..." : 控制指令);
                //消息.发布状态栏("发送:", 简要提示1);
            }
            catch (Exception ee)
            {
                var 提示1 = string.Format("出错:<{0}>", ee.Message);
                log.Log(提示1, Category.Warn, Priority.Medium);
                //消息.发布状态栏("发送:", 提示1);
            }
        }

        private void 发送指令_立即(SerialPort 串口cs, bool 十六进制, string 控制指令cs)
        {
            if (!串口cs.IsOpen) 串口cs.Open();
            定时次数 = 3;
            if (十六进制)
            {
                //var send = 转换.HexToByte(控制指令cs);
                //串口cs.Write(send, 0, send.Length);
            }
            else
            {
                var send = 控制指令cs.ToCharArray();
                串口cs.Write(send, 0, send.Length);
            }
        }

        public void 发送查询状态指令(string 查询状态指令, bool 十六进制)
        {
            var 指令 = 查询状态指令;
            if (string.IsNullOrEmpty(指令))
            {
                log.Log(string.Format("查询状态指令为空."), Category.Info, Priority.Medium);
                return;
            }
            //返回模式 = 指令模式.状态查询;
            //timer接收器.Start();
            //消息.发布状态栏("返回:", "等待...");
            发送指令try(_串口, 十六进制, 指令);
        }

        #endregion

        #region Dispose

        private bool disposed;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    if (_串口 != null)
                    {
                        _串口.Dispose();
                    }
                }
            }
            disposed = true;
        }

        ~串口控制2008()
        {
            Dispose(false);
        }

        #endregion

        public 串口控制2008(IUnityContainer 人事部cs, IEventAggregator 新闻部cs, IRegionManager 模块cs)
            : base(人事部cs, 新闻部cs, 模块cs)
        {
        }
    }
}
